﻿using System;
using Yaml.Presentation.Tokens;

namespace Yaml.Presentation.Parsing.TokenScanners {
    class TagTokenScanner : BasicTokenScanner {
        private TagTokenType type;
        private string handle;
        private string suffix;

        public TagTokenScanner(Scanner scanner)
            : base(scanner, '!') {
            this.handle = null;
            this.suffix = null;
        }

        protected override void BeforeScan() {
            base.BeforeScan();
            // Could be a simple key
            SaveSimpleKey();
        }

        protected override void ScanForToken() {
            try {
                // base.ScanForToken();  Don't go forward in this case, we want to be able to start from the ! indicator when scanning
                char ch = Reader.PeekRelative(1);
                if (ch == '<') {
                    Scanner.Forward(2); // Move past the !< indicators
                    // Verbatim tags start with < (they are of the form !<!localsuffix> or !<urisuffix>)
                    this.type = TagTokenType.Verbatim;
                    this.handle = null;
                    this.suffix = base.ScanTagContent();
                    ch = Reader.Peek();
                    if (ch != '>') {
                        throw new ScannerException("expected '>', but found '" + ch + "'");
                    }
                    Scanner.Forward(1); // Move past the > indicator
                } else if (Scanner.IsSpaceLineBreakOrNullChar(ch)) {
                    Scanner.Forward(1); // Move past the ! indicator
                    // Non-specific tags are ! followed by whitespace (there is no suffix)
                    this.type = TagTokenType.NonSpecific;
                    this.handle = "!";
                    this.suffix = null;
                } else {
                    this.handle = base.ScanTagHandle(false);
                    if (handle.EndsWith("!") ) {
                        // Named handle tags are of the form !handle!suffix
                        this.type = TagTokenType.NamedHandle;
                        this.suffix = base.ScanTagContent();
                    } else if ( handle.StartsWith("!!") ) {
                        // Secondary handle tags are of the form !!suffix
                        this.type = TagTokenType.SecondaryShorthand;
                        this.suffix = this.handle.Substring(2);
                        this.handle = "!!";
                    } else {
                        // Primary handle tags are of the form !suffix
                        this.type = TagTokenType.PrimaryShorthand;
                        this.suffix = this.handle.Substring(1);
                        this.handle = "!";
                    }
                }
            } catch (ScannerException x) {
                throw new ScannerException("while scanning a tag at " + Start.ToString() + " " + x.Message + " at " + Scanner.GetMark(), x);
            }
        }

        protected override Yaml.Presentation.Tokens.Token CreateToken() {
            return new Tokens.TagToken(Start, End, type, handle, suffix);
        }
    }
}
